// 容纳七千万个瓦片
import Tile from './TileImpl/Tile';
import isValidGeographicBbox from "./isValidGeographicBbox";
import turf from "../../../ext/turf";

class TileSet {
    public tileObj: any;

    constructor() {
        this.tileObj = {};
    }

    add(x: number, y: number, zoom: number) {
        let zObj = this.tileObj[zoom];
        if (!zObj) {
            zObj = {};
            this.tileObj[zoom] = zObj;
        }
        let xObj = this.tileObj[zoom][x];
        if (!xObj) {
            xObj = {};
            this.tileObj[zoom][x] = xObj;
        }
        xObj[y] = true;
    }

    getMaxZoom() {
        let maxZoom = 0;
        for (const zoom in this.tileObj) {
            if (Number(zoom) > maxZoom)
                maxZoom = Number(zoom);
        }
        return maxZoom;
    }

    getMinZoom() {
        let minZoom = 0;
        for (const zoom in this.tileObj) {
            if (Number(zoom) < minZoom)
                minZoom = Number(zoom);
        }
        return minZoom;
    }

    getTilingScheme()    {
        const maxZoom = this.getMaxZoom();
        const {default: TileUtil3857} = require('./TileUtil3857');
        const {default: TileUtil4326} = require('./TileUtil4326');

        const tileTool3857 = new TileUtil3857();
        const tileTool4326 = new TileUtil4326();
        if (maxZoom === 0) {
            return null;
        } else {
            // 随机获取一张最大层级的瓦片
            const randomX = Object.keys(this.tileObj[maxZoom])[0]
            const randomY = Object.keys(this.tileObj[maxZoom][randomX])[0]
            const tile = {x: Number(randomX), y: Number(randomY), zoom: Number(maxZoom)}

            const bbox3857 = tileTool3857.tileXYZToRectanglePolygon(tile.x, tile.y, tile.zoom).bbox;
            const bbox4326 = tileTool4326.tileXYZToRectanglePolygon(tile.x, tile.y, tile.zoom).bbox;

            if (isValidGeographicBbox(bbox3857)) {
                return 'layer-xyz-3857'
            } else if (isValidGeographicBbox(bbox4326)) {
                return 'layer-xyz-4326'
            } else {
                return null;
            }
        }

    }

    getRectangle() {
        const maxZoom = this.getMaxZoom();
        const tilingScheme = this.getTilingScheme();
        // 获取最大层级的全部瓦片
        const tileList = this.getAll().filter(tile => tile.zoom === maxZoom)

        const {default: TileUtil3857} = require('./TileUtil3857');
        const {default: TileUtil4326} = require('./TileUtil4326');

        const tileTool = tilingScheme === 'layer-xyz-3857' ? new TileUtil3857() : new TileUtil4326();

        if (tilingScheme === 'layer-xyz-3857') {
            const geoJson: any = {
                type: 'FeatureCollection',
                features: []
            };
            for (let i = 0; i < tileList.length; i++) {
                const json = tileTool.tileXYZToRectanglePolygon(tileList[i].x, tileList[i].y, tileList[i].zoom);
                geoJson.features.push(json);

            }
            const bbox = turf.bbox(geoJson)
            return {
                east: bbox[2],
                north: bbox[3],
                south: bbox[1],
                west: bbox[0]
            }
        }else if (tilingScheme === 'layer-xyz-4326') {
            const geoJson: any = {
                type: 'FeatureCollection',
                features: []
            };
            for (let i = 0; i < tileList.length; i++) {
                const json = tileTool.tileXYZToRectanglePolygon(tileList[i].x, tileList[i].y, tileList[i].zoom);
                geoJson.features.push(json);

            }
            const bbox = turf.bbox(geoJson)
            return {
                east: bbox[2],
                north: bbox[3],
                south: bbox[1],
                west: bbox[0]
            }
        }

        return {
            east: 180,
            north: 90,
            south: -90,
            west: -180
        }
    }

    getLayerProperties() {
        const minZoom = this.getMinZoom();
        const maxZoom = this.getMaxZoom();
        const tilingScheme = this.getTilingScheme();
        const rectangle = this.getRectangle();
        return {
            scheme: tilingScheme,
            minimumLevel: minZoom,
            maximumLevel: maxZoom,
            rectangle: rectangle,
        }
    }


    delete(x: number, y: number, zoom: number) {
        if (this.tileObj[zoom] && this.tileObj[zoom][x] && this.tileObj[zoom][x][y])
            this.tileObj[zoom][x][y] = false;
    }

    getAll(): Tile[] {
        const result = [];
        for (const zoom in this.tileObj) {
            for (const x in this.tileObj[zoom]) {
                for (const y in this.tileObj[zoom][x]) {
                    if (this.tileObj[zoom][x][y] === true) {
                        result.push(new Tile(Number(x), Number(y), Number(zoom)));
                    }
                }
            }
        }
        return result;
    }

    clear() {
        this.tileObj = {};
    }
}

export default TileSet;
